home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / h / vd2 / system / VDString.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-10-13  |  24.3 KB  |  939 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #ifndef f_VD2_SYSTEM_VDSTRING_H
  27. #define f_VD2_SYSTEM_VDSTRING_H
  28.  
  29. #ifdef _MSC_VER
  30.     #pragma once
  31. #endif
  32.  
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <stdarg.h>
  36. #include <stddef.h>
  37.  
  38. #include <vd2/system/vdtypes.h>
  39. #include <vd2/system/text.h>
  40.  
  41. ///////////////////////////////////////////////////////////////////////////
  42.  
  43. class VDStringSpanA {
  44. public:
  45.     typedef char                    value_type;
  46.     typedef uint32                    size_type;
  47.     typedef ptrdiff_t                difference_type;
  48.     typedef value_type&                reference;
  49.     typedef const value_type&        const_reference;
  50.     typedef value_type *            pointer;
  51.     typedef const value_type *        const_pointer;
  52.     typedef pointer                    iterator;
  53.     typedef const_pointer            const_iterator;
  54.  
  55.     static const size_type npos = (size_type)-1;
  56.  
  57.     VDStringSpanA() 
  58.         : mpBegin(const_cast<value_type *>(sNull))
  59.         , mpEnd(const_cast<value_type *>(sNull))
  60.     {
  61.     }
  62.  
  63.     explicit VDStringSpanA(const value_type *s)
  64.         : mpBegin(const_cast<value_type *>(s))
  65.         , mpEnd(const_cast<value_type *>(s) + strlen(s))
  66.     {
  67.     }
  68.  
  69.     VDStringSpanA(const value_type *s, const value_type *t)
  70.         : mpBegin(const_cast<value_type *>(s))
  71.         , mpEnd(const_cast<value_type *>(t))
  72.     {
  73.     }
  74.  
  75.     // 21.3.2 iterators
  76.     const_iterator        begin() const        { return mpBegin; }
  77.     const_iterator        end() const            { return mpEnd; }
  78.  
  79.     // 21.3.3 capacity
  80.     size_type            size() const        { return mpEnd - mpBegin; }
  81.     size_type            length() const        { return mpEnd - mpBegin; }
  82.     bool                empty() const        { return mpBegin == mpEnd; }
  83.  
  84.     // 21.3.4 element access
  85.     const_reference        operator[](size_type pos) const    { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  86.     const_reference        at(size_type pos) const            { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  87.  
  88.     const_reference        front() const        { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  89.     const_reference        back() const        { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  90.  
  91.     // 21.3.6 string operations
  92.     const_pointer        data() const        { return mpBegin; }
  93.  
  94.     size_type copy(value_type *dst, size_type n, size_type pos = 0) const {
  95.         size_type len = (size_type)(mpEnd - mpBegin);
  96.         VDASSERT(pos <= len);
  97.  
  98.         len -= pos;
  99.         if (n > len)
  100.             n = len;
  101.  
  102.         memcpy(dst, mpBegin + pos, n*sizeof(value_type));
  103.         return n;
  104.     }
  105.  
  106.     size_type find(value_type c, size_type pos = 0) const {
  107.         VDASSERT(pos <= (size_type)(mpEnd - mpBegin));
  108.         const void *p = memchr(mpBegin + pos, c, mpEnd - (mpBegin + pos));
  109.  
  110.         return p ? (const value_type *)p - mpBegin : npos;
  111.     }
  112.  
  113.     const VDStringSpanA subspan(size_type pos = 0, size_type n = npos) const {
  114.         
  115.         size_type len = (size_type)(mpEnd - mpBegin);
  116.         VDASSERT(pos <= len);
  117.  
  118.         len -= pos;
  119.         if (n > len)
  120.             n = len;
  121.  
  122.         value_type *p = mpBegin + pos;
  123.         return VDStringSpanA(p, p+n);
  124.     }
  125.  
  126. protected:
  127.     friend bool operator==(const VDStringSpanA& x, const VDStringSpanA& y);
  128.     friend bool operator==(const VDStringSpanA& x, const char *y);
  129.  
  130.     value_type *mpBegin;
  131.     value_type *mpEnd;
  132.  
  133.     static const value_type sNull[1];
  134. };
  135.  
  136. inline bool operator==(const VDStringSpanA& x, const VDStringSpanA& y) { VDStringSpanA::size_type len = (VDStringSpanA::size_type)(x.mpEnd - x.mpBegin); return len == (VDStringSpanA::size_type)(y.mpEnd - y.mpBegin) && !memcmp(x.mpBegin, y.mpBegin, len*sizeof(char)); }
  137. inline bool operator==(const VDStringSpanA& x, const char *y) { size_t len = strlen(y); return len == (size_t)(x.mpEnd - x.mpBegin) && !memcmp(x.mpBegin, y, len*sizeof(char)); }
  138. inline bool operator==(const char *x, const VDStringSpanA& y) { return y == x; }
  139.  
  140. inline bool operator!=(const VDStringSpanA& x, const VDStringSpanA& y) { return !(x == y); }
  141. inline bool operator!=(const VDStringSpanA& x, const char *y) { return !(x == y); }
  142. inline bool operator!=(const char *x, const VDStringSpanA& y) { return !(y == x); }
  143.  
  144. class VDStringA : public VDStringSpanA {
  145. public:
  146.     typedef VDStringA                this_type;
  147.  
  148.     // 21.3.1 construct/copy/destroy
  149.  
  150.     VDStringA()
  151.         : mpEOS(const_cast<value_type *>(sNull))
  152.     {
  153.     }
  154.  
  155.     VDStringA(const this_type& x)
  156.         : mpEOS(const_cast<value_type *>(sNull))
  157.     {
  158.         assign(x);
  159.     }
  160.  
  161.     explicit VDStringA(const value_type *s)
  162.         : mpEOS(const_cast<value_type *>(sNull))
  163.     {
  164.         assign(s);
  165.     }
  166.  
  167.     explicit VDStringA(size_type n)
  168.         : mpEOS(const_cast<value_type *>(sNull))
  169.     {
  170.         resize(n);
  171.     }
  172.  
  173.     VDStringA(const value_type *s, size_type n)
  174.         : mpEOS(const_cast<value_type *>(sNull))
  175.     {
  176.         assign(s, n);
  177.     }
  178.  
  179.     ~VDStringA() {
  180.         if (mpBegin != sNull)
  181.             delete[] mpBegin;
  182.     }
  183.  
  184.     this_type& operator=(const value_type *s) {
  185.         assign(s);
  186.         return *this;
  187.     }
  188.  
  189.     this_type& operator=(const this_type& str) {
  190.         assign(str);
  191.         return *this;
  192.     }
  193.  
  194.     // 21.3.2 iterators
  195.     using VDStringSpanA::begin;
  196.     using VDStringSpanA::end;
  197.  
  198.     iterator            begin()                { return mpBegin; }
  199.     iterator            end()                { return mpEnd; }
  200.  
  201.     // 21.3.3 capacity (COMPLETE)
  202.     void resize(size_type n) {
  203.         size_type current = (size_type)(mpEnd - mpBegin);
  204.  
  205.         if (n < current) {
  206.             mpEnd = mpBegin + n;
  207.             mpEnd[0] = 0;
  208.         } else if (n > current)
  209.             resize_slow(n, current);
  210.     }
  211.  
  212.     void resize(size_type n, value_type v) {
  213.         size_type current = (size_type)(mpEnd - mpBegin);
  214.  
  215.         if (n < current) {
  216.             mpEnd = mpBegin + n;
  217.             mpEnd[0] = 0;
  218.         } else if (n > current)
  219.             resize_slow(n, current, v);
  220.     }
  221.  
  222.     size_type            capacity() const    { return mpEOS - mpBegin; }
  223.  
  224.     void reserve(size_t n) {
  225.         size_type current = (size_type)(mpEOS - mpBegin);
  226.  
  227.         if (n > current)
  228.             reserve_slow(n, current);
  229.     }
  230.  
  231.     void clear() {
  232.         if (mpEnd != mpBegin) {
  233.             mpEnd = mpBegin;
  234.             mpEnd[0] = 0;
  235.         }
  236.     }
  237.  
  238.     // 21.3.4 element access
  239.     using VDStringSpanA::operator[];
  240.     using VDStringSpanA::at;
  241.     using VDStringSpanA::front;
  242.     using VDStringSpanA::back;
  243.  
  244.     reference            operator[](size_type pos)        { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  245.     reference            at(size_type pos)                { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  246.     reference            front()                { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  247.     reference            back()                { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  248.  
  249.     // 21.3.5 modifiers
  250.     this_type& operator+=(const this_type& str) {
  251.         return append(str.mpBegin, str.mpEnd);
  252.     }
  253.  
  254.     this_type& operator+=(const value_type *s) {
  255.         return append(s, s+strlen(s));
  256.     }
  257.  
  258.     this_type& operator+=(value_type c) {
  259.         if (mpEnd == mpEOS)
  260.             push_back_extend();
  261.  
  262.         *mpEnd++ = c;
  263.         *mpEnd = 0;
  264.         return *this;
  265.     }
  266.  
  267.     this_type& append(const this_type& str) {
  268.         return append(str.mpBegin, str.mpEnd);
  269.     }
  270.  
  271.     this_type& append(const this_type& str, size_type pos, size_type n) {
  272.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  273.         VDASSERT(pos <= len);
  274.  
  275.         len -= pos;
  276.         if (n > len)
  277.             n = len;
  278.  
  279.         return append(str.mpBegin + pos, str.mpBegin + pos + n);
  280.     }
  281.  
  282.     this_type& append(const value_type *s, size_type n) {
  283.         return append(s, s+n);
  284.     }
  285.  
  286.     this_type& append(const value_type *s) {
  287.         return append(s, s+strlen(s));
  288.     }
  289.  
  290.     this_type& append(const value_type *s, const value_type *t) {
  291.         if (s != t) {
  292.             size_type current_size = (size_type)(mpEnd - mpBegin);
  293.             size_type current_capacity = (size_type)(mpEOS - mpBegin);
  294.             size_type n = (size_type)(t - s);
  295.  
  296.             if (current_capacity - current_size < n)
  297.                 reserve_amortized_slow(n, current_size, current_capacity);
  298.  
  299.             memcpy(mpBegin + current_size, s, n*sizeof(value_type));
  300.             mpEnd += n;
  301.             *mpEnd = 0;
  302.         }
  303.         return *this;
  304.     }
  305.  
  306.     void push_back(const value_type c) {
  307.         if (mpEnd == mpEOS)
  308.             push_back_extend();
  309.  
  310.         *mpEnd++ = c;
  311.         *mpEnd = 0;
  312.     }
  313.  
  314.     this_type& assign(const this_type& str) {
  315.         return assign(str.mpBegin, str.mpEnd);
  316.     }
  317.  
  318.     this_type& assign(const this_type& str, size_type pos, size_type n) {
  319.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  320.         VDASSERT(pos <= len);
  321.  
  322.         len -= pos;
  323.         if (n > len)
  324.             n = len;
  325.  
  326.         return assign(str.mpBegin + pos, str.mpBegin + pos + n);
  327.     }
  328.  
  329.     this_type& assign(const value_type *s, size_type n) {
  330.         return assign(s, s+n);
  331.     }
  332.  
  333.     this_type& assign(const value_type *s) {
  334.         return assign(s, s+strlen(s));
  335.     }
  336.  
  337.     this_type& assign(size_type n, value_type c) {
  338.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  339.  
  340.         if (current_capacity < n)
  341.             reserve_slow(n, current_capacity);
  342.  
  343.         if (mpBegin != sNull) {
  344.             mpEnd = mpBegin;
  345.             while(n--)
  346.                 *mpEnd++ = c;
  347.         }
  348.  
  349.         return *this;
  350.     }
  351.  
  352.     this_type& assign(const value_type *s, const value_type *t) {
  353.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  354.         size_type n = (size_type)(t - s);
  355.  
  356.         if (current_capacity < n)
  357.             reserve_slow(n, current_capacity);
  358.  
  359.         if (mpBegin != sNull) {
  360.             memcpy(mpBegin, s, sizeof(value_type)*n);
  361.             mpEnd = mpBegin + n;
  362.             *mpEnd = 0;
  363.         }
  364.  
  365.         return *this;
  366.     }
  367.  
  368.     this_type& insert(iterator it, value_type c) {
  369.         if (mpEnd == mpEOS) {
  370.             size_type pos = (size_type)(it - mpBegin);
  371.             push_back_extend();
  372.             it = mpBegin + pos;
  373.         }
  374.  
  375.         memmove(it + 1, it, (mpEnd - it + 1)*sizeof(value_type));
  376.         *it = c;
  377.         ++mpEnd;
  378.         return *this;
  379.     }
  380.  
  381.     this_type& erase(size_type pos = 0, size_type n = npos) {
  382.         size_type len = (size_type)(mpEnd - mpBegin);
  383.  
  384.         VDASSERT(pos <= len);
  385.         len -= pos;
  386.         if (n > len)
  387.             n = len;
  388.  
  389.         if (n) {
  390.             size_type pos2 = pos + n;
  391.             memmove(mpBegin + pos, mpBegin + pos2, (len + 1 - n)*sizeof(value_type));
  392.             mpEnd -= n;
  393.         }
  394.  
  395.         return *this;
  396.     }
  397.  
  398.     iterator erase(iterator x) {
  399.         VDASSERT(x != mpEnd);
  400.  
  401.         memmove(x, x+1, (mpEnd - x)*sizeof(value_type));
  402.         --mpEnd;
  403.         return x;
  404.     }
  405.  
  406.     iterator erase(iterator first, iterator last) {
  407.         VDASSERT(last >= first);
  408.  
  409.         memmove(first, last, ((mpEnd - last) + 1)*sizeof(value_type));
  410.         mpEnd -= (last - first);
  411.         return first;
  412.     }
  413.  
  414.     this_type& replace(size_type pos, size_type n1, const value_type *s, size_type n2) {
  415.         size_type len = (size_type)(mpEnd - mpBegin);
  416.  
  417.         VDASSERT(pos <= len);
  418.         size_type limit = len - pos;
  419.         if (n1 > limit)
  420.             n1 = limit;
  421.  
  422.         size_type len2 = len - n1 + n2;
  423.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  424.  
  425.         if (current_capacity < len2)
  426.             reserve_slow(len2, current_capacity);
  427.  
  428.         memmove(mpBegin + pos + n2, mpBegin + pos + n1, (limit - n1 + 1) * sizeof(value_type));
  429.         memcpy(mpBegin + pos, s, n2*sizeof(value_type));
  430.         mpEnd = mpBegin + len2;
  431.         return *this;
  432.     }
  433.  
  434.     void swap(this_type& x) {
  435.         value_type *p;
  436.  
  437.         p = mpBegin;    mpBegin = x.mpBegin;    x.mpBegin = p;
  438.         p = mpEnd;        mpEnd = x.mpEnd;        x.mpEnd = p;
  439.         p = mpEOS;        mpEOS = x.mpEOS;        x.mpEOS = p;
  440.     }
  441.  
  442.     // 21.3.6 string operations
  443.     const_pointer        c_str() const        { return mpBegin; }
  444.  
  445.     this_type& sprintf(const value_type *format, ...);
  446.     this_type& append_sprintf(const value_type *format, ...);
  447.     this_type& append_vsprintf(const value_type *format, va_list val);
  448.  
  449. protected:
  450.     void push_back_extend();
  451.     void resize_slow(size_type n, size_type current_size);
  452.     void resize_slow(size_type n, size_type current_size, value_type c);
  453.     void reserve_slow(size_type n, size_type current_capacity);
  454.     void reserve_amortized_slow(size_type n, size_type current_size, size_type current_capacity);
  455.  
  456.     char *mpEOS;
  457. };
  458.  
  459. ///////////////////////////////////////////////////////////////////////////
  460.  
  461. inline VDStringA operator+(const VDStringA& str, const VDStringA& s) {
  462.     VDStringA result;
  463.     result.reserve(str.size() + s.size());
  464.     result.assign(str);
  465.     result.append(s);
  466.     return result;
  467. }
  468.  
  469. inline VDStringA operator+(const VDStringA& str, const char *s) {
  470.     VDStringA result;
  471.     result.reserve(str.size() + strlen(s));
  472.     result.assign(str);
  473.     result.append(s);
  474.     return result;
  475. }
  476.  
  477. inline VDStringA operator+(const VDStringA& str, char c) {
  478.     VDStringA result;
  479.     result.reserve(str.size() + 1);
  480.     result.assign(str);
  481.     result += c;
  482.     return result;
  483. }
  484.  
  485. ///////////////////////////////////////////////////////////////////////////
  486.  
  487. class VDStringSpanW {
  488. public:
  489.     typedef wchar_t                    value_type;
  490.     typedef uint32                    size_type;
  491.     typedef ptrdiff_t                difference_type;
  492.     typedef value_type&                reference;
  493.     typedef const value_type&        const_reference;
  494.     typedef value_type *            pointer;
  495.     typedef const value_type *        const_pointer;
  496.     typedef pointer                    iterator;
  497.     typedef const_pointer            const_iterator;
  498.  
  499.     static const size_type npos = (size_type)-1;
  500.  
  501.     VDStringSpanW() 
  502.         : mpBegin(const_cast<value_type *>(sNull))
  503.         , mpEnd(const_cast<value_type *>(sNull))
  504.     {
  505.     }
  506.  
  507.     explicit VDStringSpanW(const value_type *s)
  508.         : mpBegin(const_cast<value_type *>(s))
  509.         , mpEnd(const_cast<value_type *>(s) + wcslen(s))
  510.     {
  511.     }
  512.  
  513.     VDStringSpanW(const value_type *s, const value_type *t)
  514.         : mpBegin(const_cast<value_type *>(s))
  515.         , mpEnd(const_cast<value_type *>(t))
  516.     {
  517.     }
  518.  
  519.     // 21.3.2 iterators
  520.     const_iterator        begin() const        { return mpBegin; }
  521.     const_iterator        end() const            { return mpEnd; }
  522.  
  523.     // 21.3.3 capacity
  524.     size_type            size() const        { return mpEnd - mpBegin; }
  525.     size_type            length() const        { return mpEnd - mpBegin; }
  526.     bool                empty() const        { return mpBegin == mpEnd; }
  527.  
  528.     // 21.3.4 element access
  529.     const_reference        operator[](size_type pos) const    { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  530.     const_reference        at(size_type pos) const            { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  531.  
  532.     const_reference        front() const        { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  533.     const_reference        back() const        { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  534.  
  535.     // 21.3.6 string operations
  536.     const_pointer        data() const        { return mpBegin; }
  537.  
  538.     size_type copy(value_type *dst, size_type n, size_type pos = 0) const {
  539.         size_type len = (size_type)(mpEnd - mpBegin);
  540.         VDASSERT(pos <= len);
  541.  
  542.         len -= pos;
  543.         if (n > len)
  544.             n = len;
  545.  
  546.         memcpy(dst, mpBegin + pos, n*sizeof(value_type));
  547.         return n;
  548.     }
  549.  
  550.     size_type find(value_type c, size_type pos = 0) const {
  551.         VDASSERT(pos <= (size_type)(mpEnd - mpBegin));
  552.         const void *p = wmemchr(mpBegin + pos, c, mpEnd - (mpBegin + pos));
  553.  
  554.         return p ? (const value_type *)p - mpBegin : npos;
  555.     }
  556.  
  557.     // extensions
  558.     const VDStringSpanW subspan(size_type pos, size_type n) const {
  559.         size_type len = (size_type)(mpEnd - mpBegin);
  560.         VDASSERT(pos <= len);
  561.  
  562.         len -= pos;
  563.         if (n > len)
  564.             n = len;
  565.  
  566.         value_type *p = mpBegin + pos;
  567.         return VDStringSpanW(p, p+n);
  568.     }
  569.  
  570. protected:
  571.     friend bool operator==(const VDStringSpanW& x, const VDStringSpanW& y);
  572.     friend bool operator==(const VDStringSpanW& x, const wchar_t *y);
  573.  
  574.     value_type *mpBegin;
  575.     value_type *mpEnd;
  576.  
  577.     static const value_type sNull[1];
  578. };
  579.  
  580. inline bool operator==(const VDStringSpanW& x, const VDStringSpanW& y) { VDStringA::size_type len = (VDStringSpanW::size_type)(x.mpEnd - x.mpBegin); return len == (VDStringSpanW::size_type)(y.mpEnd - y.mpBegin) && !memcmp(x.mpBegin, y.mpBegin, len*sizeof(wchar_t)); }
  581. inline bool operator==(const VDStringSpanW& x, const wchar_t *y) { size_t len = wcslen(y); return len == (size_t)(x.mpEnd - x.mpBegin) && !memcmp(x.mpBegin, y, len*sizeof(wchar_t)); }
  582. inline bool operator==(const wchar_t *x, const VDStringSpanW& y) { return y == x; }
  583.  
  584. inline bool operator!=(const VDStringSpanW& x, const VDStringSpanW& y) { return !(x == y); }
  585. inline bool operator!=(const VDStringSpanW& x, const wchar_t *y) { return !(x == y); }
  586. inline bool operator!=(const wchar_t *x, const VDStringSpanW& y) { return !(y == x); }
  587.  
  588. class VDStringW : public VDStringSpanW {
  589. public:
  590.     typedef VDStringW                this_type;
  591.  
  592.     // 21.3.1 construct/copy/destroy
  593.  
  594.     VDStringW()
  595.         : mpEOS(const_cast<value_type *>(sNull))
  596.     {
  597.     }
  598.  
  599.     VDStringW(const this_type& x)
  600.         : mpEOS(const_cast<value_type *>(sNull))
  601.     {
  602.         assign(x);
  603.     }
  604.  
  605.     explicit VDStringW(const value_type *s)
  606.         : mpEOS(const_cast<value_type *>(sNull))
  607.     {
  608.         assign(s);
  609.     }
  610.  
  611.     explicit VDStringW(size_type n)
  612.         : mpEOS(const_cast<value_type *>(sNull))
  613.     {
  614.         resize(n);
  615.     }
  616.  
  617.     VDStringW(const value_type *s, size_type n)
  618.         : mpEOS(const_cast<value_type *>(sNull))
  619.     {
  620.         assign(s, n);
  621.     }
  622.  
  623.     VDStringW(const value_type *s, const value_type *t)
  624.         : mpEOS(const_cast<value_type *>(sNull))
  625.     {
  626.         assign(s, t);
  627.     }
  628.  
  629.     ~VDStringW() {
  630.         if (mpBegin != sNull)
  631.             delete[] mpBegin;
  632.     }
  633.  
  634.     this_type& operator=(const wchar_t *s) {
  635.         assign(s);
  636.         return *this;
  637.     }
  638.  
  639.     this_type& operator=(const this_type& str) {
  640.         assign(str);
  641.         return *this;
  642.     }
  643.  
  644.     // 21.3.2 iterators
  645.     using VDStringSpanW::begin;
  646.     using VDStringSpanW::end;
  647.     iterator            begin()                { return mpBegin; }
  648.     iterator            end()                { return mpEnd; }
  649.  
  650.     // 21.3.3 capacity (COMPLETE)
  651.     void resize(size_type n) {
  652.         size_type current = (size_type)(mpEnd - mpBegin);
  653.  
  654.         if (n < current) {
  655.             mpEnd = mpBegin + n;
  656.             mpEnd[0] = 0;
  657.         } else if (n > current)
  658.             resize_slow(n, current);
  659.     }
  660.  
  661.     void resize(size_type n, value_type v) {
  662.         size_type current = (size_type)(mpEnd - mpBegin);
  663.  
  664.         if (n < current) {
  665.             mpEnd = mpBegin + n;
  666.             mpEnd[0] = 0;
  667.         } else if (n > current)
  668.             resize_slow(n, current);
  669.         wmemset(mpBegin, v, n);
  670.     }
  671.  
  672.     size_type            capacity() const    { return mpEOS - mpBegin; }
  673.  
  674.     void reserve(size_t n) {
  675.         size_type current = (size_type)(mpEOS - mpBegin);
  676.  
  677.         if (n > current)
  678.             reserve_slow(n, current);
  679.     }
  680.  
  681.     void clear() {
  682.         if (mpEnd != mpBegin) {
  683.             mpEnd = mpBegin;
  684.             mpEnd[0] = 0;
  685.         }
  686.     }
  687.  
  688.     // 21.3.4 element access
  689.     using VDStringSpanW::operator[];
  690.     using VDStringSpanW::at;
  691.     using VDStringSpanW::front;
  692.     using VDStringSpanW::back;
  693.     reference            operator[](size_type pos)        { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  694.     reference            at(size_type pos)                { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  695.     reference            front()                { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  696.     reference            back()                { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  697.  
  698.     // 21.3.5 modifiers
  699.     this_type& operator+=(const this_type& str) {
  700.         return append(str.mpBegin, str.mpEnd);
  701.     }
  702.  
  703.     this_type& operator+=(const value_type *s) {
  704.         return append(s, s+wcslen(s));
  705.     }
  706.  
  707.     this_type& operator+=(value_type c) {
  708.         if (mpEnd == mpEOS)
  709.             push_back_extend();
  710.  
  711.         *mpEnd++ = c;
  712.         *mpEnd = 0;
  713.         return *this;
  714.     }
  715.  
  716.     this_type& append(const this_type& str) {
  717.         return append(str.mpBegin, str.mpEnd);
  718.     }
  719.  
  720.     this_type& append(const this_type& str, size_type pos, size_type n) {
  721.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  722.         VDASSERT(pos <= len);
  723.  
  724.         len -= pos;
  725.         if (n > len)
  726.             n = len;
  727.  
  728.         return append(str.mpBegin + pos, str.mpBegin + pos + n);
  729.     }
  730.  
  731.     this_type& append(const value_type *s, size_type n) {
  732.         return append(s, s+n);
  733.     }
  734.  
  735.     this_type& append(const value_type *s) {
  736.         return append(s, s+wcslen(s));
  737.     }
  738.  
  739.     this_type& append(const value_type *s, const value_type *t) {
  740.         if (s != t) {
  741.             size_type current_size = (size_type)(mpEnd - mpBegin);
  742.             size_type current_capacity = (size_type)(mpEOS - mpBegin);
  743.             size_type n = (size_type)(t - s);
  744.  
  745.             if (current_capacity - current_size < n)
  746.                 reserve_amortized_slow(n, current_size, current_capacity);
  747.  
  748.             memcpy(mpBegin + current_size, s, n*sizeof(value_type));
  749.             mpEnd += n;
  750.             *mpEnd = 0;
  751.         }
  752.         return *this;
  753.     }
  754.  
  755.     void push_back(const value_type c) {
  756.         if (mpEnd == mpEOS)
  757.             push_back_extend();
  758.  
  759.         *mpEnd++ = c;
  760.         *mpEnd = 0;
  761.     }
  762.  
  763.     this_type& assign(const this_type& str) {
  764.         return assign(str.mpBegin, str.mpEnd);
  765.     }
  766.  
  767.     this_type& assign(const this_type& str, size_type pos, size_type n) {
  768.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  769.         VDASSERT(pos <= len);
  770.  
  771.         len -= pos;
  772.         if (n > len)
  773.             n = len;
  774.  
  775.         return assign(str.mpBegin + pos, str.mpBegin + pos + n);
  776.     }
  777.  
  778.     this_type& assign(const value_type *s, size_type n) {
  779.         return assign(s, s+n);
  780.     }
  781.  
  782.     this_type& assign(const value_type *s) {
  783.         return assign(s, s+wcslen(s));
  784.     }
  785.  
  786.     this_type& assign(size_type n, value_type c) {
  787.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  788.  
  789.         if (current_capacity < n)
  790.             reserve_slow(n, current_capacity);
  791.  
  792.         if (mpBegin != sNull) {
  793.             mpEnd = mpBegin;
  794.             while(n--)
  795.                 *mpEnd++ = c;
  796.         }
  797.  
  798.         return *this;
  799.     }
  800.  
  801.     this_type& assign(const value_type *s, const value_type *t) {
  802.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  803.         size_type n = (size_type)(t - s);
  804.  
  805.         if (current_capacity < n)
  806.             reserve_slow(n, current_capacity);
  807.  
  808.         if (mpBegin != sNull) {
  809.             memcpy(mpBegin, s, sizeof(value_type)*n);
  810.             mpEnd = mpBegin + n;
  811.             *mpEnd = 0;
  812.         }
  813.  
  814.         return *this;
  815.     }
  816.  
  817.     this_type& insert(iterator it, value_type c) {
  818.         if (mpEnd == mpEOS) {
  819.             size_type pos = (size_type)(it - mpBegin);
  820.             push_back_extend();
  821.             it = mpBegin + pos;
  822.         }
  823.  
  824.         memmove(it + 1, it, (mpEnd - it + 1)*sizeof(value_type));
  825.         *it = c;
  826.         ++mpEnd;
  827.         return *this;
  828.     }
  829.  
  830.     this_type& erase(size_type pos = 0, size_type n = npos) {
  831.         size_type len = (size_type)(mpEnd - mpBegin);
  832.  
  833.         VDASSERT(pos <= len);
  834.         len -= pos;
  835.         if (n > len)
  836.             n = len;
  837.  
  838.         if (n) {
  839.             size_type pos2 = pos + n;
  840.             memmove(mpBegin + pos, mpBegin + pos2, (len + 1 - n)*sizeof(value_type));
  841.             mpEnd -= n;
  842.         }
  843.  
  844.         return *this;
  845.     }
  846.  
  847.     iterator erase(iterator x) {
  848.         VDASSERT(x != mpEnd);
  849.  
  850.         memmove(x, x+1, (mpEnd - x)*sizeof(value_type));
  851.         --mpEnd;
  852.         return x;
  853.     }
  854.  
  855.     iterator erase(iterator first, iterator last) {
  856.         VDASSERT(last >= first);
  857.  
  858.         memmove(first, last, ((mpEnd - last) + 1)*sizeof(value_type));
  859.         mpEnd -= (last - first);
  860.         return first;
  861.     }
  862.  
  863.     this_type& replace(size_type pos, size_type n1, const value_type *s, size_type n2) {
  864.         size_type len = (size_type)(mpEnd - mpBegin);
  865.  
  866.         VDASSERT(pos <= len);
  867.         size_type limit = len - pos;
  868.         if (n1 > limit)
  869.             n1 = limit;
  870.  
  871.         size_type len2 = len - n1 + n2;
  872.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  873.  
  874.         if (current_capacity < len2)
  875.             reserve_slow(len2, current_capacity);
  876.  
  877.         memmove(mpBegin + pos + n2, mpBegin + pos + n1, (limit - n1 + 1) * sizeof(value_type));
  878.         memcpy(mpBegin + pos, s, n2*sizeof(value_type));
  879.         mpEnd = mpBegin + len2;
  880.         return *this;
  881.     }
  882.  
  883.     void swap(this_type& x) {
  884.         value_type *p;
  885.  
  886.         p = mpBegin;    mpBegin = x.mpBegin;    x.mpBegin = p;
  887.         p = mpEnd;        mpEnd = x.mpEnd;        x.mpEnd = p;
  888.         p = mpEOS;        mpEOS = x.mpEOS;        x.mpEOS = p;
  889.     }
  890.  
  891.     // 21.3.6 string operations
  892.     const_pointer        c_str() const        { return mpBegin; }
  893.  
  894.     this_type& sprintf(const value_type *format, ...);
  895.     this_type& append_sprintf(const value_type *format, ...);
  896.     this_type& append_vsprintf(const value_type *format, va_list val);
  897.  
  898. protected:
  899.     void push_back_extend();
  900.     void resize_slow(size_type n, size_type current_size);
  901.     void reserve_slow(size_type n, size_type current_capacity);
  902.     void reserve_amortized_slow(size_type n, size_type current_size, size_type current_capacity);
  903.  
  904.     value_type *mpEOS;
  905. };
  906.  
  907. ///////////////////////////////////////////////////////////////////////////
  908.  
  909. inline VDStringW operator+(const VDStringW& str, const VDStringW& s) {
  910.     VDStringW result;
  911.     result.reserve(str.size() + s.size());
  912.     result.assign(str);
  913.     result.append(s);
  914.     return result;
  915. }
  916.  
  917. inline VDStringW operator+(const VDStringW& str, const wchar_t *s) {
  918.     VDStringW result;
  919.     result.reserve(str.size() + wcslen(s));
  920.     result.assign(str);
  921.     result.append(s);
  922.     return result;
  923. }
  924.  
  925. inline VDStringW operator+(const VDStringW& str, wchar_t c) {
  926.     VDStringW result;
  927.     result.reserve(str.size() + 1);
  928.     result.assign(str);
  929.     result += c;
  930.     return result;
  931. }
  932.  
  933. ///////////////////////////////////////////////////////////////////////////
  934.  
  935. typedef VDStringA                VDString;
  936.  
  937.  
  938. #endif
  939.